package com.atwisdom.star.core.bsl.business.Impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.atwisdom.star.common.util.EasyExcel;
import com.atwisdom.star.common.util.ExpressionUtil;
import com.atwisdom.star.common.util.JsonUtil;
import com.atwisdom.star.common.util.UuidTool;
import com.atwisdom.star.common.vo.*;
import com.atwisdom.star.core.bsl.business.BusinessBslService;
import com.atwisdom.star.core.dao.pojo.modelClass.hier.HierInstance;
import com.atwisdom.star.core.dao.pojo.modelClass.staticLogic.StaticLogicInstance;
import com.atwisdom.star.core.dsl.modelClass.consume.Impl.ConsumeInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.hier.HierInstanceDslService;
import com.atwisdom.star.core.dsl.modelClass.logic.Impl.LogicInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.resource.Impl.ResourceInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.routing.Impl.RoutingInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.staticLogic.Impl.StaticLogicInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.tank.Impl.TankInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.twins.Impl.TwinsInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.utils.DictionaryHier;
import com.atwisdom.star.core.dsl.modelClass.utils.DictionaryHierContent;
import com.atwisdom.star.core.dsl.modelClass.workCenter.Impl.WorkCenterInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.util.AutoGenUtil;
import com.atwisdom.star.exception.pojo.BusinessException;
import com.googlecode.aviator.AviatorEvaluator;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
@Service
public class BusinessBslServiceImpl implements BusinessBslService {
    private WorkCenterInstanceDslServiceImpl workCenterInstanceDslService;
    private ConsumeInstanceDslServiceImpl consumeInstanceDslService;
    private ResourceInstanceDslServiceImpl resourceInstanceDslService;

    private StaticLogicInstanceDslServiceImpl staticLogicInstanceDslService;

    private LogicInstanceDslServiceImpl logicInstanceDslService;

    private TwinsInstanceDslServiceImpl twinsInstanceDslService;

    private TankInstanceDslServiceImpl tankInstanceDslService;

    private HierInstanceDslService hierInstanceDslService;

    private RoutingInstanceDslServiceImpl routingInstanceDslService;

    @Autowired
    public void setWorkCenterInstanceDslService(WorkCenterInstanceDslServiceImpl workCenterInstanceDslService) {
        this.workCenterInstanceDslService = workCenterInstanceDslService;
    }

    @Autowired
    public void setTankInstanceDslService(TankInstanceDslServiceImpl tankInstanceDslService) {
        this.tankInstanceDslService = tankInstanceDslService;
    }

    @Autowired
    public void setTwinsInstanceDslService(TwinsInstanceDslServiceImpl twinsInstanceDslService) {
        this.twinsInstanceDslService = twinsInstanceDslService;
    }

    @Autowired
    public void setLogicInstanceDslService(LogicInstanceDslServiceImpl logicInstanceDslService) {
        this.logicInstanceDslService = logicInstanceDslService;
    }

    @Autowired
    public void setStaticLogicInstanceDslService(StaticLogicInstanceDslServiceImpl staticLogicInstanceDslService) {
        this.staticLogicInstanceDslService = staticLogicInstanceDslService;
    }

    @Autowired
    public void setResourceInstanceDslService(ResourceInstanceDslServiceImpl resourceInstanceDslService) {
        this.resourceInstanceDslService = resourceInstanceDslService;
    }

    @Autowired
    public void setConsumeInstanceDslService(ConsumeInstanceDslServiceImpl consumeInstanceDslService) {
        this.consumeInstanceDslService = consumeInstanceDslService;
    }

    @Autowired
    public void setHierInstanceDslService(HierInstanceDslService hierInstanceDslService) {
        this.hierInstanceDslService = hierInstanceDslService;
    }

    @Autowired
    public void setRoutingInstanceDslService(RoutingInstanceDslServiceImpl routingInstanceDslService) {
        this.routingInstanceDslService = routingInstanceDslService;
    }

    @Autowired
    private AutoGenUtil autoGenUtil;

    //实体移入的容器节点名
    private final String ENTER_CONTAINER = "ENTER_CONTAINER";
    //实体离开容器的节点名
    private final String LEAVE_CONTAINER = "LEAVE_CONTAINER";
    //容器中转移实体节点名
    private final String TRANSFER_ENTITY = "TRANSFER_ENTITY";
    //容器中需要创建实体节点名
    private final String CREATE_ENTITY = "CREATE_ENTITY";


    /**
     * 创建实例并增加入到容器中 （创建实例并加入工作中心中容器节点上）
     * 1，读出workCenter
     * 2，在workCenter的hier'实体'获取创建实体的模型信息
     * 3，新增同时更新values
     * 4，在workCenter的hier'容器'获取容器的模型信息
     * 5，添加节点并且绑定link
     *
     * @param data 工作中心类名
     * @return 返回新增的实体
     */
    @Transactional(rollbackFor = Exception.class)
    public JSONObject createInstanceToContainer(JSONObject data) {
        //工作中心类名
        String wcClassName = data.getString("wcClassName");
        //工作中心实例id
        String wcId = data.getString("wcId");
        //工作中心关联实例属性值
        String createInsNodeId = data.getString("createInsNodeId");
        String enterNodeId = data.getString("enterNodeId");
        String name = data.getString("name");
        JSONObject values = data.getJSONObject("values");

        //查询工作中心容器
        HierInstance hierInstanceNode = this.hierInstanceDslService.fetchByNodeId(ModelType.WorkCenter.getCode(), wcClassName, Long.valueOf(wcId), createInsNodeId);
        if (hierInstanceNode == null) {
            throw new BusinessException("999999", "没有要添加的实例，添加实例操作失败！");
        }

        JSONObject newInstance = createInstance(hierInstanceNode, name, values);
        Long instanceId = newInstance.getLong("id");
        HierInstance enterNode = this.hierInstanceDslService.fetchByNodeId(ModelType.WorkCenter.getCode(), wcClassName, Long.valueOf(wcId), enterNodeId);
        //查找实体移入的容器节点，如果不存在抛异常
        if (enterNode == null) {
            throw new BusinessException("999999", "没有要进入的容器，添加实例到容器失败！");
        }

        //绑定实例到工作中心Hier实例上
        enterNode.setName(newInstance.getString("name"));
        this.bindInstanceToHier(instanceId, enterNode);
        //返回新增的实体
        return newInstance;
    }

    /**
     * 绑定实例到工作中心Hier实例上
     *
     * @param linkId    实例id
     * @param enterNode 绑定实例
     */
    private void bindInstanceToHier(Long linkId, HierInstance enterNode) {
        String nodeType = enterNode.getNodeType();
        if (StringUtils.isNotBlank(nodeType) && "list".equalsIgnoreCase(nodeType)) {
            this.hierInstanceDslService.addByParentHierInstance(enterNode, linkId);
        } else {
            enterNode.setLinkId(linkId);
            this.hierInstanceDslService.updateById(enterNode);
        }
    }

    /**
     * 将一个实例从工作中心容器某个节点转移到另外一个容器
     * 1、工作中心实例节点不解绑，
     * 2、另一个容器节点需要绑定实例
     * 3，读出workCenter
     * 4，在workCenter的hier'实体'获取要转移的实例link信息
     * 5，将转移实例添加到移入容器中，添加节点并且绑定link
     *
     * @param data 参数
     * @return 返回工作中心容器
     */
    public JSONObject transferInstanceWCToContainer(JSONObject data) {
        //工作中心类名
        String wcClassName = data.getString("wcClassName");
        //工作中心实例id
        String wcId = data.getString("wcId");

        String transferInsNodeId = data.getString("transferInsNodeId");
        String enterModel = data.getString("enterModel");
        String enterClassName = data.getString("enterClassName");
        Long enterContainerId = data.getLong("enterContainerId");
        String enterNodeId = data.getString("enterNodeId");

        //查询工作中心容器
        HierInstance hierInstanceNode = this.hierInstanceDslService.fetchByNodeId(ModelType.WorkCenter.getCode(), wcClassName, Long.valueOf(wcId), transferInsNodeId);
        if (hierInstanceNode == null) {
            throw new BusinessException("999999", "要转移的实体节点不存在，转移实例失败！");
        }
        JSONObject jsonObject = this.execTransferInstanceWCToContainer(wcClassName, wcId, enterModel, enterClassName, enterContainerId, enterNodeId, transferInsNodeId);
        return jsonObject;
    }

    /**
     * 将一个实例从工作中心容器某个节点转移到另外一个容器
     * 1、工作中心实例节点不解绑，
     * 2、另一个容器节点需要绑定实例
     * 3，读出workCenter
     * 4，在workCenter的hier'实体'获取要转移的实例link信息
     * 5，将转移实例添加到移入容器中，添加节点并且绑定link
     *
     * @param data 参数
     * @return 返回工作中心容器
     */
    public List<JSONObject> batchTransferInstanceWCToContainer(JSONObject data) {
        //工作中心类名
        String wcClassName = data.getString("wcClassName");
        //工作中心实例id
        String wcId = data.getString("wcInstanceId");

        String transferInsNodeIds = data.getString("transferInsNodeId");

        String[] array = transferInsNodeIds.split(",");
        List<String> transferInsNodeIdList = Arrays.asList(array);

        String enterModel = data.getString("enterModel");
        String enterClassName = data.getString("enterClassName");
        Long enterContainerId = data.getLong("enterContainerId");
        String enterNodeId = data.getString("enterNodeId");

        List<JSONObject> insJsonList = new ArrayList<>();
        transferInsNodeIdList.forEach(transferInsNodeId -> {
            //查询工作中心容器
            JSONObject jsonObject = this.execTransferInstanceWCToContainer(wcClassName, wcId, enterModel, enterClassName, enterContainerId, enterNodeId, transferInsNodeId);
            insJsonList.add(jsonObject);
        });
        //绑定实体到容器
        return insJsonList;
    }

    /**
     * 执行 一个实例从工作中心容器某个节点转移到另外一个容器
     *
     * @param wcClassName       工作中心类名
     * @param wcId              工作中心实例id
     * @param enterModel        转移进入容器模型
     * @param enterClassName    转移进入容器类名
     * @param enterContainerId  转移进入容器实例id
     * @param enterNodeId       转移进入容器节点
     * @param transferInsNodeId 转移实例节点Id
     * @return 返回转移的实例
     */
    private JSONObject execTransferInstanceWCToContainer(String wcClassName, String wcId, String enterModel, String enterClassName, Long enterContainerId, String enterNodeId, String transferInsNodeId) {
        HierInstance hierInstanceNode = this.hierInstanceDslService.fetchByNodeId(ModelType.WorkCenter.getCode(), wcClassName, Long.valueOf(wcId), transferInsNodeId);
        if (hierInstanceNode == null) {
            throw new BusinessException("999999", "要转移的实体节点不存在，转移实例失败！");
        }
        //解绑实例id
        Long insId = Long.valueOf(hierInstanceNode.getLinkId());

        //设置工作中心转移实例节点状态
        this.hierInstanceDslService.updateInnerStatus(hierInstanceNode.getId());
        HierInstance enterNode = new HierInstance();
        enterNode.setLinkModel(enterModel);
        enterNode.setLinkClassName(enterClassName);
        enterNode.setLinkId(enterContainerId);
        enterNode.setNodeId(enterNodeId);
        JSONObject jsonObject = bindInstanceToContainer(insId, enterNode);
        return jsonObject;
    }

    /**
     * 更新工作中心节点link实例
     *
     * @param data 参数据
     *             1、wcInstanceId 工作中心实例
     *             2、wcNodeId 工作中心节点
     * @return 返回已更新实例
     */
    public JSONObject updateInstanceByNode(JSONObject data) {
        long wcInstanceId = data.getLong("wcInstanceId");
        String wcNodeId = data.getString("wcNodeId");
        HierInstance hierNode = this.hierInstanceDslService.fetchByNodeId(ModelType.WorkCenter.getCode(), wcInstanceId, wcNodeId);
        JSONObject insValues = data.getJSONObject("values");
        return updateInstance(hierNode, insValues);
    }

    private JSONObject updateInstance(HierInstance hierNode, JSONObject insValues) {
        Long linkId = hierNode.getLinkId();
        String linkClassName = hierNode.getLinkClassName();
        String linkModel = hierNode.getLinkModel();
        String linkType = hierNode.getLinkType();
        JSONObject insJson = null;
        JSONObject updateJson = new JSONObject();
        updateJson.put("id", linkId);
        updateJson.put("className", linkClassName);
        updateJson.put("type", linkType);
        updateJson.put("values", insValues);
        switch (linkModel) {
            case "consume":
                insJson = consumeInstanceDslService.updateById(updateJson);
                break;
            case "resource":
                insJson = resourceInstanceDslService.updateById(updateJson);
                break;
            case "tank":
                insJson = tankInstanceDslService.updateById(updateJson);
                break;
            case "logic":
                insJson = logicInstanceDslService.updateById(updateJson);
                break;
            default:
                break;
        }

        return insJson;
    }

    /**
     * 设置工作中心某节点状态
     * 1、根据model、wcId、wcNodeId,查询容器实例节点
     * 2、设置节点状态
     *
     * @param data
     */
    public Boolean dealWorkCenterHierNodeStatus(JSONObject data) {
        try {
            long wcId = data.getLong("wcId");
            String wcNodeId = data.getString("wcNodeId");
            String status = data.getString("status");
            this.hierInstanceDslService.updateStatus(ModelType.WorkCenter.getCode(), wcId, wcNodeId, status);
            return true;
        } catch (Exception ex) {
            throw new BusinessException("999999", "设置工作中心某节点状态失败！");
        }
    }

    /**
     * 设置工作中心状态
     * 1、查询工作中心实例
     * 2、设置状态
     *
     * @param data 参数
     */
    public Boolean dealWorkCenterStatus(JSONObject data) {
        try {
            Long routingId = data.getLong("routingId");
            Long wcId = data.getLong("wcId");
            String status = data.getString("status");
            this.workCenterInstanceDslService.updateStatus(wcId, status);
            this.routingInstanceDslService.updateNodeStatus(wcId, routingId, status);
            return true;
        } catch (Exception ex) {
            throw new BusinessException("999999", "设置工作中心状态失败！");
        }
    }

    /**
     * 将一个实例从一个容器某个节点转移到另外一个容器某个节点下
     * 1、 转出容器实例节点解绑，
     * 2、 移入容器节点绑定实例
     *
     * @param data 参数
     * @return 返回工作中心容器
     */
    public JSONObject transferInstanceContainerToContainer(JSONObject data) {
        //工作中心类名
//        String wcClassName = data.getString("wcClassName");
//        //工作中心实例id
//        String wcId = data.getString("wcId");
//
//        String transferInsNodeId = data.getString("transferInsNodeId");
//        String enterNodeId = data.getString("enterNodeId");
//
//        String leaveNodeId = data.getString("leaveNodeId");


        //离开容器参数
        String leaveModel = data.getString("leaveModel");
        String leaveClassName = data.getString("leaveClassName");
        String leaveContainerId = data.getString("leaveContainerId");
        String leaveNodeId = data.getString("leaveNodeId");


        //进入容器参数
        String enterModel = data.getString("enterModel");
        String enterClassName = data.getString("enterClassName");
        String enterContainerId = data.getString("enterContainerId");
        String enterNodeId = data.getString("enterNodeId");

        //查询工作中心容器
        HierInstance leaveNode = this.hierInstanceDslService.fetchByNodeId(leaveModel, leaveClassName, Long.valueOf(leaveContainerId), leaveNodeId);
        if (leaveNode == null) {
            throw new BusinessException("999999", "要转移的实体节点不存在，转移实例失败！");
        }
        //解绑实例id
        Long insId = Long.valueOf(leaveNode.getLinkId());

        //查找实体移入的容器节点，如果不存在抛异常
        HierInstance enterNode = this.hierInstanceDslService.fetchByNodeId(enterModel, enterClassName, Long.valueOf(enterContainerId), enterNodeId);
        if (enterNode == null) {
            throw new BusinessException("999999", "没有实体移入容器节点，移入实体失败！");
        }


        //查找实体移出的容器节点，如果不存在抛异常
//        HierInstance leaveNode = this.hierInstanceDslService.fetchByNodeId(ModelType.WorkCenter.getCode(), wcClassName, Long.valueOf(wcId),leaveNodeId);
//        if (leaveNode == null) {
//            throw new BusinessException("999999", "没有实体移出容器，移出实体失败！");
//        }

        //从容器中解绑实体
        this.unbindInstanceFromContainer(insId, leaveNode);

        //绑定实体到容器
        return bindInstanceToContainer(insId, enterNode);
    }

    /**
     * 创建实体
     *
     * @param hierInstance 创建实例节点
     * @param name         创建实例名称
     * @param values       创建实例属性
     * @return 反回实例json
     */
    private JSONObject createInstance(HierInstance hierInstance, String name, JSONObject values) {
        //创建实体
        String linkType = hierInstance.getLinkType();
        String linkClassName = hierInstance.getLinkClassName();
        String linkModel = hierInstance.getLinkModel();
        if (StringUtils.isBlank(name)) {
            name = linkClassName;
        }

        JSONObject insJson = null;
        switch (linkModel) {
            case "consume":
                insJson = consumeInstanceDslService.add(linkType, linkClassName, name, values);
                hierInstance.setLinkId(insJson.getLong("id"));
                break;
            case "resource":
                insJson = resourceInstanceDslService.add(linkType, linkClassName, name, values);
                hierInstance.setLinkId(insJson.getLong("id"));
                break;
            case "tank":
                insJson = tankInstanceDslService.add(linkType, linkClassName, name, values);
                hierInstance.setLinkId(insJson.getLong("id"));
                break;
            case "logic":
                insJson = logicInstanceDslService.add(linkType, linkClassName, name, values);
                hierInstance.setLinkId(insJson.getLong("id"));
                break;
            default:
                break;
        }

        return insJson;
    }

    /**
     * 查找操作的容器
     *
     * @param insId     要绑定实例Id
     * @param enterNode 容器节点
     * @return 返回容器
     */
    public JSONObject bindInstanceToContainer(Long insId, HierInstance enterNode) {
        String nodeId = enterNode.getNodeId();
        String linkClassName = enterNode.getLinkClassName();
        String linkModel = enterNode.getLinkModel();
        Long linkId = Long.valueOf(enterNode.getLinkId());
        JSONObject jsonObject = null;
        switch (linkModel) {
            case "staticLogic":
                jsonObject = staticLogicInstanceDslService.bindEntityToHier(linkClassName, nodeId, insId);
                break;
            case "logic":
                jsonObject = logicInstanceDslService.bindEntityToHier(linkId, linkClassName, nodeId, insId);
                break;
            case "twins":
                jsonObject = twinsInstanceDslService.bindEntityToHier(linkClassName, nodeId, insId);
                break;
            case "tank":
                jsonObject = tankInstanceDslService.bindEntityToHier(linkId, linkClassName, nodeId, insId);
                break;
        }
        return jsonObject;
    }

    /**
     * 从一个容器节点解绑一个实例
     *
     * @param insId     要解绑的实例
     * @param leaveNode 解绑定容器节点
     * @return 返回解绑的容器
     */
    public JSONObject unbindInstanceFromContainer(Long insId, HierInstance leaveNode) {
        Long linkId = Long.valueOf(leaveNode.getLinkId());
        String nodeId = leaveNode.getNodeId();
        String linkModel = leaveNode.getLinkModel();
        String linkClassName = leaveNode.getLinkClassName();
        JSONObject jsonObject = null;
        switch (linkModel) {
            case "staticLogic":
                jsonObject = staticLogicInstanceDslService.unbindEntityToHier(linkClassName, nodeId, insId);
                break;
            case "logic":
                jsonObject = logicInstanceDslService.unbindEntityToHier(linkId, nodeId, insId);
                break;
            case "twins":
                jsonObject = twinsInstanceDslService.unbindEntityToHier(linkClassName, nodeId, insId);
                break;
            case "tank":
                jsonObject = tankInstanceDslService.unbindEntityToHier(linkId, nodeId, insId);
                break;
        }
        return jsonObject;
    }

    /**
     * 创建实体并增加到静态逻辑容器中 （创建实体并加入容器）
     * 1，读出workCenter
     * 2，在workCenter的hier'实体'获取创建实体的模型信息
     * 3，新增同时更新values
     * 4，在workCenter的hier'容器'获取容器的模型信息
     * 5，添加节点并且绑定link
     *
     * @param data 工作中心类名
     * @return 返回新增的实体
     */
    @Transactional(rollbackFor = Exception.class)
    public JSONObject createEntityToContainer(JSONObject data) {
        //工作中心类名
        String wcClassName = data.getString("wcClassName");
        //工作中心实例id
        Long wcId = data.getLong("wcId");
        //工作中心关联实体属性值
        JSONObject values = data.getJSONObject("values");
        //查询工作中心容器
        JSONObject hier = workCenterInstanceDslService.queryHierById(wcId);
        DictionaryHier dictHier = JSONObject.parseObject(JSON.toJSONString(hier), DictionaryHier.class);
        List<DictionaryHierContent> content = dictHier.getContent();
        //查找要创建实体节点
        DictionaryHierContent entityNode = content.stream().filter(c -> c.getName().equalsIgnoreCase(CREATE_ENTITY)).findFirst().orElse(null);
        //检查要创建的实体节点是否存在，不存在执行异常
        if (entityNode == null || !entityNode.getName().equalsIgnoreCase(CREATE_ENTITY)) {
            throw new BusinessException("999999", "没有要添加的实体，添加实体失败！");
        }
        //查找实体移入的容器节点，如果不存在抛异常
        DictionaryHierContent containerNode = content.stream().filter(c -> c.getName().equalsIgnoreCase(ENTER_CONTAINER)).findFirst().orElse(null);
        if (containerNode == null) {
            throw new BusinessException("999999", "没有静态逻辑容器，添加实体失败！");
        }

        JSONObject entity = this.createEntity(entityNode, values);
        Long id = entity.getLong("id");
        entityNode.getLink().put("id", id);
        //绑定实体到容器
        return bindEntityToContainer(entityNode, containerNode);
    }

    /**
     * 将一个实体从一个容器转移到另外一个容器 （容器间转移）
     * 1，读出workCenter
     * 2，在workCenter的hier'实体'获取要转移的实体link信息
     * 3，将转移实体从移出容器称除
     * 4，将转移实体添加到移入容器中，添加节点并且绑定link
     * @param data 参数
     * @return 返回工作中心容器
     */
    /**
     * @param data
     * @return
     */
    public JSONObject transferEntityToContainer(JSONObject data) {
        //工作中心类名
        String wcClassName = data.getString("wcClassName");
        //工作中心实例id
        Long wcId = data.getLong("wcId");
        //查询工作中心容器
        JSONObject hier = workCenterInstanceDslService.queryHierById(wcId);
        DictionaryHier dictHier = JSONObject.parseObject(JSON.toJSONString(hier), DictionaryHier.class);
        List<DictionaryHierContent> content = dictHier.getContent();
        //查找要转移实体节点
        DictionaryHierContent entityNode = content.stream().filter(c -> c.getName().equalsIgnoreCase(TRANSFER_ENTITY)).findFirst().orElse(null);
        //检查要创建的实体节点是否存在，不存在执行异常
        if (entityNode == null) {
            throw new BusinessException("999999", "没有要转移的实体节点不存在，转移实体失败！");
        }

        //查找实体移入的容器节点，如果不存在抛异常
        DictionaryHierContent enterContainerNode = content.stream().filter(c -> c.getName().equalsIgnoreCase(ENTER_CONTAINER)).findFirst().orElse(null);
        if (enterContainerNode == null) {
            throw new BusinessException("999999", "没有实体移入容器节点，移入实体失败！");
        }

        //查找实体移出的容器节点，如果不存在抛异常
        DictionaryHierContent leaveContainerNode = content.stream().filter(c -> c.getName().equalsIgnoreCase(LEAVE_CONTAINER)).findFirst().orElse(null);
        if (leaveContainerNode == null) {
            throw new BusinessException("999999", "没有实体移出容器，移出实体失败！");
        }
        //从容器中解绑实体
        this.unbindEntityFromContainer(entityNode, leaveContainerNode);

        //绑定实体到容器
        return bindEntityToContainer(entityNode, enterContainerNode);
    }

    /**
     * 创建实体
     *
     * @param entityNode
     * @return
     */
    private JSONObject createEntity(DictionaryHierContent entityNode, JSONObject values) {
        //创建实体
        JSONObject entityLink = entityNode.getLink();
        String model = entityLink.getString("model");
        String type = entityLink.getString("type");
        String className = entityLink.getString("className");
        JSONObject entityJson = null;
        switch (model) {
            case "consume":
                entityJson = consumeInstanceDslService.add(type, className, className, values);
                entityLink.put("id", entityJson.getLong("id"));
                break;
            case "resource":
                entityJson = resourceInstanceDslService.add(type, className, className, values);
                entityLink.put("id", entityJson.getLong("id"));
                break;
            default:
                break;
        }

        return entityJson;
    }

    /**
     * 查找操作的容器
     *
     * @param containerNode 容器节点
     * @return 返回容器
     */
    private JSONObject bindEntityToContainer(DictionaryHierContent entityNode, DictionaryHierContent containerNode) {
        JSONObject link = containerNode.getLink();
        String className = link.getString("className");
        String model = link.getString("model");
        String nodeId = link.getString("nodeId");
        Long id = link.getLong("id");
        JSONObject entityNodeLink = entityNode.getLink();
        Long entityId = entityNodeLink.getLong("id");
        JSONObject jsonObject = null;
        switch (model) {
            case "staticLogic":
                jsonObject = staticLogicInstanceDslService.bindEntityToHier(className, nodeId, entityId);
                break;
            case "logic":
                jsonObject = logicInstanceDslService.bindEntityToHier(id, className, nodeId, entityId);
                break;
            case "twins":
                jsonObject = twinsInstanceDslService.bindEntityToHier(className, nodeId, entityId);
                break;
            case "tank":
                jsonObject = tankInstanceDslService.bindEntityToHier(id, className, nodeId, entityId);
                break;
        }
        return jsonObject;
    }

    private JSONObject unbindEntityFromContainer(DictionaryHierContent entityNode, DictionaryHierContent containerNode) {
        JSONObject link = containerNode.getLink();
        String className = link.getString("className");
        String model = link.getString("model");
        String nodeId = link.getString("nodeId");
        Long id = link.getLong("id");
        JSONObject entityNodeLink = entityNode.getLink();
        Long entityId = entityNodeLink.getLong("id");
        JSONObject jsonObject = null;
        switch (model) {
            case "staticLogic":
                jsonObject = staticLogicInstanceDslService.unbindEntityToHier(className, nodeId, entityId);
                break;
            case "logic":
                jsonObject = logicInstanceDslService.unbindEntityToHier(id, nodeId, entityId);
                break;
            case "twins":
                jsonObject = twinsInstanceDslService.unbindEntityToHier(className, nodeId, entityId);
                break;
            case "tank":
                jsonObject = tankInstanceDslService.unbindEntityToHier(id, nodeId, entityId);
                break;
        }
        return jsonObject;
    }

    // region 泰正增加

    /**
     * 创建实例并增加入到容器中 （创建实例并加入容器节点上）
     *
     * @param data 工作中心类名
     * @return 返回新增的实体
     */
    @Transactional(rollbackFor = Exception.class)
    public JSONObject createOtherInstanceToContainer(JSONObject data) {
        String model = data.getString("model");
        String className = data.getString("className");
        Long containerId = data.getLong("containerId");
        String createInsNodeId = data.getString("createInsNodeId");
        String enterNodeId = data.getString("enterNodeId");
        String name = data.getString("name");
        JSONObject values = data.getJSONObject("values");

        HierInstance hierInstanceNode = hierInstanceDslService.fetchByNodeId(model, className, containerId, createInsNodeId);
        if (hierInstanceNode == null) {
            throw new BusinessException("999999", "没有要添加的实例，添加实例操作失败！");
        }

        JSONObject newInstance = createInstance(hierInstanceNode, name, values);
        Long instanceId = newInstance.getLong("id");
        HierInstance enterNode = hierInstanceDslService.fetchByNodeId(model, className, containerId, enterNodeId);
        //查找实体移入的容器节点，如果不存在抛异常
        if (enterNode == null) {
            throw new BusinessException("999999", "没有要进入的容器，添加实例到容器失败！");
        }

        //绑定实例到Hier实例上
        enterNode.setName(newInstance.getString("name"));
        this.bindInstanceToHier(instanceId, enterNode);
        //返回新增的实体
        return newInstance;
    }


    /**
     * 更新节点link实例
     *
     * @param data 参数据
     *             1、containerId 容器实例
     *             2、nodeId 节点
     * @return 返回已更新实例
     */
    public JSONObject updateOtherInstanceByNode(JSONObject data) {
        String model = data.getString("model");
        long containerId = data.getLong("containerId");
        String nodeId = data.getString("nodeId");
        HierInstance hierNode = hierInstanceDslService.fetchByNodeId(model, containerId, nodeId);
        JSONObject insValues = data.getJSONObject("values");
        return updateInstance(hierNode, insValues);
    }

    /**
     * 更新节点link实例, 用于同时更新多个实例的一个字段
     * 业务如下：
     * 1. 批量更新看板列表状态
     *
     * @param data 参数据
     *             1、containerId 容器实例
     *             2、nodeId 节点
     */
    public void updateOtherInstanceByParent(JSONObject data) {
        String model = data.getString("model");
        long containerId = data.getLong("containerId");
        String parentNodeId = data.getString("parentNodeId");
        JSONObject insValues = data.getJSONObject("values");
        List<HierInstance> hierInstanceList = hierInstanceDslService.fetchByParentNodeId(model, containerId, parentNodeId);
        hierInstanceList.forEach(d -> {
            updateInstance(d, insValues);
        });
    }

    /**
     * 添加list的下级节点，并link到指定实例数据
     *
     * @param data
     * @return
     */
    public List<HierInstance> addNodeAndLinkInstanceToListContainer(JSONObject data) {
        return hierInstanceDslService.addNodeAndLinkInstanceToListContainer(data);
    }

    /**
     * 解绑link的实例，并删除相应的节点
     *
     * @param data
     * @return
     */
    public boolean deleteNodeByLink(JSONObject data) {
        return hierInstanceDslService.deleteNodeByLink(data);
    }


    /**
     * 获取link数据并分组
     * 分组的字段名称，可以是任一属性，包括查询与非查询属性
     *
     * @return
     */
    public Map<Object, List<JSONObject>> queryHierLinkAndGroupBy(JSONObject data) {
        Map<Object, List<JSONObject>> result = new HashMap<>();
        String condition = data.getString("condition");
        String hierValueCondition = data.getString("hierValueCondition");
        if (StrUtil.isNotBlank(hierValueCondition)) {
            hierValueCondition = hierValueCondition.replace("'$", "insValues->'$");
            condition += " and " + hierValueCondition;
        }
        String model = data.getString("model");
        Long containerId = data.getLong("containerId");
        String className = data.getString("className");
        String linkModel = data.getString("linkModel");
        String linkClassName = data.getString("linkClassName");
        String linkType = data.getString("linkType");
        String linkCondition = data.getString("linkCondition");
        List<HierInstance> hierInstanceList = hierInstanceDslService.queryByContainerId(model, containerId, className, condition);
        List<HierInstance> newHierInstanceList = hierInstanceDslService.filterNodeList(hierInstanceList, (HierInstance hierInstance) ->
                StrUtil.isNotBlank(hierInstance.getLinkModel()) && hierInstance.getLinkModel().equals(linkModel) &&
                        StrUtil.isNotBlank(hierInstance.getLinkClassName()) && hierInstance.getLinkClassName().equals(linkClassName) &&
                        StrUtil.isNotBlank(hierInstance.getLinkType()) && hierInstance.getLinkType().equals(linkType));
        String linkIds = newHierInstanceList.stream().map(d -> String.valueOf(d.getLinkId())).collect(Collectors.joining(","));
        String newLinkCondition = StrUtil.isNotBlank(linkCondition) ? linkCondition + " && id in( " + linkIds + ")" : "  id in( " + linkIds + ")";
        //分组的字段名称
        String groupByKey = data.getString("groupByKey");
        switch (linkModel) {
            case "logic":
                result = logicInstanceDslService.queryAndGroupBy(newLinkCondition, linkClassName, groupByKey);
                break;
        }
        return result;
    }

    /**
     * 根据当前记录的Hier数据，更新其他记录的Hier数据
     *
     * @param data let createNextInstanceWithHier =
     *             {
     *             "data": {
     *             // 采购到货单
     *             "model": "logic",
     *             "className": "PurchaseArrivalOrder",
     *             "containerId": 123,
     *             // 采购订单
     *             "prevModel": "logic",
     *             "prevClassName": "PurchaseOrder",
     *             "prevContainerId": 56,
     *             "isCheck": true,  // 是否校验公式：审核时是加法，需要校验，反审时是减法，不需要校验
     *             "checkField": "material_bcode", // 校验失败时，需要返回出错行的某个字段的值；
     *             // 子表字段map
     *             "subFieldMap": {
     *             "arrivalQuantity": {  // 采购订单的累计到货数量 = 采购订单的累计到货数量 + 到货单上的数量
     *             "sign": "+", // 公式的符号：+ -; 审批时，累计到货数量是+，反审时，累计到货数量是-
     *             "current": "quantity",
     *             }
     *             },
     *             }
     *             }
     */
    public void updateAnotherByCurrent(JSONObject data) {
        String currentModel = data.getString("currentModel");
        Long currentContainerId = data.getLong("currentContainerId");
        String currentParentId = data.getString("currentParentId");

        String anotherModel = data.getString("anotherModel");
        Long anotherContainerId = data.getLong("anotherContainerId");
        // Long anotherParentId = data.getLong("anotherParentId ");

        List<HierInstance> currentHierInstanceList = hierInstanceDslService.queryByContainerId(currentModel, currentContainerId);
        if (StrUtil.isNotBlank(currentParentId)) {
            currentHierInstanceList = hierInstanceDslService.filterNodeList(currentHierInstanceList, p -> p.getParentId().equals(currentParentId));
        }
        List<HierInstance> anotherHierInstanceList = hierInstanceDslService.queryByContainerId(anotherModel, anotherContainerId);
        // anotherHierInstanceList = hierInstanceDslService.filterNodeList(anotherHierInstanceList,  p -> p.getParentId().equals(anotherParentId));

        // 需要指定子表间数据定位的字段，如：到货单中保存了订单子表中的数ID， 字段名为：purchaseOrder_sub_id:id
        String uniqueFieldPathMap = data.getString("uniqueFieldPathMap");
        String[] uniqueFieldPathArray = uniqueFieldPathMap.split(":");
        currentHierInstanceList.forEach(currentInstance -> {
            Object anotherUniqueFieldValue = JsonUtil.get(currentInstance, uniqueFieldPathArray[0]);
            if (anotherUniqueFieldValue != null) {
                anotherHierInstanceList.forEach(anotherInstance -> {
                    Object anotherValue = JsonUtil.get(anotherInstance, uniqueFieldPathArray[1]);
                    if (anotherUniqueFieldValue.equals(anotherValue) || String.valueOf(anotherUniqueFieldValue).equals(String.valueOf(anotherValue))) {
                        Boolean checkResult = checkAnotherInstance(data, currentInstance, anotherInstance);
                        if (!checkResult) {
                            throwCheckException(data, anotherInstance);
                        }
                        // 更新公式 arrivalQuantity : ${arrivalQuantity} + ${current.quantity}
                        updateAnotherInstance(data, currentInstance, anotherInstance);
                    }
                });
            }
        });
        // 更新anotherInstance数据
        hierInstanceDslService.updateBatchById(anotherHierInstanceList);
    }

    /**
     * 抛出规则检验异常
     *
     * @param data
     * @param anotherInstance
     */
    private void throwCheckException(JSONObject data, HierInstance anotherInstance) {
        JSONObject checkException = data.getJSONObject("checkException");
        String exceptionFieldPath = checkException.getString("fieldPath");
        String exceptionMessage = checkException.getString("message");
        Object exceptionFieldValue = JsonUtil.get(anotherInstance, exceptionFieldPath);
        String exceptionFieldName = checkException.getString("fieldName");
        String throwStr = exceptionMessage + ", 异常数据: " + exceptionFieldName + " = " + exceptionFieldValue;
        throw new BusinessException(throwStr);
    }

    /**
     * 检查是否符合规则
     * ${arrivalQuantity} > ${arrivalQuantity} + ${current.quantity}
     *
     * @param data
     * @param currentInstance
     * @param anotherInstance
     */
    private Boolean checkAnotherInstance(JSONObject data, HierInstance currentInstance, HierInstance anotherInstance) {
        String checkExpression = data.getString("checkExpression");
        Boolean checkFlag = data.getBoolean("checkFlag");
        if (checkFlag) {
            // 找到了记录，开始更新数据，更新的数据，是一个公式，需要计算，arrivalQuantity > arrivalQuantity + quantity
            checkExpression = handleExpression(currentInstance, anotherInstance, checkExpression);
            Object result = AviatorEvaluator.execute(checkExpression);
            return result.equals(true);
        } else {
            // 不用检查，默认为检查通过
            return true;
        }

    }

    /**
     * 计算出公式的值，并更新字段
     *
     * @param data
     * @param currentInstance
     * @param anotherInstance
     */
    private void updateAnotherInstance(JSONObject data, HierInstance currentInstance, HierInstance anotherInstance) {
        String updateValueExpression = data.getString("updateValueExpression");
        String[] expressionArray = updateValueExpression.split(":");
        // 找到了记录，开始更新数据，更新的数据，是一个公式，需要计算，arrivalQuantity = arrivalQuantity + quantity
        updateValueExpression = handleExpression(currentInstance, anotherInstance, expressionArray[1]);
        Object resultValue = AviatorEvaluator.execute(updateValueExpression);
        anotherInstance.getValues().put(expressionArray[0], resultValue);
    }

    private String handleExpression(HierInstance currentInstance, HierInstance anotherInstance, String expression) {
        String[] expressionVars = ExpressionUtil.handleExpression(expression);
        for (int i = 0; i < expressionVars.length; i++) {
            String expressionVarName = expressionVars[i];
            Object varValue = null;
            if (expressionVarName.startsWith("current.")) {
                // 说明需要取当前数据中的值
                varValue = JsonUtil.get(currentInstance, expressionVarName.substring("current.".length()));
            } else {
                // 取原有的值
                varValue = JsonUtil.get(anotherInstance, expressionVarName);
            }
            if (varValue == null) {
                varValue = 0;
            }
            expression = expression.replace("${" + expressionVarName + "}", String.valueOf(varValue));
        }
        return expression;
    }

    /**
     * 根据关联的数据更新当前数据，如：供应商更新后，供应商价表中的供应商信息要相应更新
     * 在页面或模型中增加属性，确定需要同步更新的className,
     * needUpdateData: {"logic":[c1, c2], "consume":[c1,c2]}
     *
     * @param data
     */
    public void updateByLinkData(JSONObject data) {
        JSONObject needUpdateData = data.getJSONObject("needUpdateData");
        needUpdateData.forEach((k, v) -> {
            if ("logic".equals(k)) {
                JSONArray classNameArray = JsonUtil.toJSONArray(v);
                List<String> classNameList = JSONObject.parseArray(classNameArray.toJSONString(), String.class);
                List<JSONObject> instanceList = logicInstanceDslService.queryWithoutHierByclassNameList(classNameList);
                List<Long> idList = instanceList.stream().map(d -> d.getLong("id")).collect(Collectors.toList());
                JSONArray idArray = JsonUtil.toJSONArray(idList);
                data.put("ids", idArray);
                logicInstanceDslService.updateByBatchId(data);
            }
        });
    }

    /**
     * 删除校验：循环数组，有一条存在记录，就返回当前记录的 message
     * [
     * {action: "QUERY", model: "logic", className: "saleOrder", condition: "deptId=1", hierValueCondition: "", message: "销售订单已使用，不能删除；" },
     * {action: "QUERY_HIER", model: "logic", className: "saleOutBound", condition: "", hierValueCondition: "deptId=2", message: "销售出库单已使用，不能删除；"},
     * ]
     *
     * @param dataObj 参数
     * @return 返回结果
     */
    @Override
    public ResultInfo<?> emptyRecord(JSONObject dataObj) {
        boolean isEmpty = true;
        JSONArray data = dataObj.getJSONArray("data");
        for (Object obj : data) {
            JSONObject jsonObject = (JSONObject) obj;
            String action = jsonObject.getString("action");
            String model = jsonObject.getString("model");
            String className = jsonObject.getString("className");
            String condition = jsonObject.getString("condition");
            String hierValueCondition = jsonObject.getString("hierValueCondition");
            String message = jsonObject.getString("message");
            String fieldName = jsonObject.getString("fieldName");
            Map<String, String> msgMap = new HashMap<>();
            if ("QUERY_HIER".equalsIgnoreCase(action)) {
                List<HierInstance> hInsList = this.hierInstanceDslService.query(model, className, hierValueCondition);
                hInsList.forEach(hIns -> {
                    String fieldValue = hIns.getValues().getString(fieldName);
                    if (StringUtils.isNotBlank(fieldValue)) {
                        msgMap.put(fieldValue, fieldValue);
                    }
                });
                isEmpty = CollectionUtil.isEmpty(hInsList);
            } else {
                List<JSONObject> list = new ArrayList<>();
                switch (model) {
                    case "resource":
                        list = this.resourceInstanceDslService.query(condition, className, null);
                        isEmpty = CollectionUtil.isEmpty(list);
                        break;
                    case "consume":
                        list = this.consumeInstanceDslService.query(condition, className, null);
                        isEmpty = CollectionUtil.isEmpty(list);
                        break;
                    case "logic":
                        list = this.logicInstanceDslService.query(condition, className, null, hierValueCondition);
                        isEmpty = CollectionUtil.isEmpty(list);
                        break;
                    case "staticLogic":
                        list = this.staticLogicInstanceDslService.query(condition, className, null, hierValueCondition, false);
                        isEmpty = CollectionUtil.isEmpty(list);
                        break;
                    case "twins":
                        list = this.twinsInstanceDslService.query(condition, className, null, hierValueCondition);
                        isEmpty = CollectionUtil.isEmpty(list);
                        break;
                }

                list.forEach(ins -> {
                    JSONObject values = ins.getJSONObject("values");
                    String fieldValue = values.getString(fieldName);
                    if (StringUtils.isNotBlank(fieldValue)) {
                        msgMap.put(fieldValue, fieldValue);
                    }
                });
            }
            if (!isEmpty) {
                String result = msgMap.keySet().stream().collect(Collectors.joining(","));
                return JsonResult.error(StatusCode.ERROR_DELETE.getCode(), message + result);
            }
        }
        return JsonResult.success(StatusCode.SUCCESS);
    }

    private List<JSONObject> excelValueList = new ArrayList<>();

    @Transactional(rollbackFor = Exception.class)
    public boolean importInsFile(MultipartFile file, ExcelImportHeader excelImportHeader) {
        InputStream inputStream;
        String fileName;
        try {
            fileName = file.getOriginalFilename();
            inputStream = file.getInputStream();
        } catch (Exception e) {
            throw new BusinessException("999999", "导入文件出错" + e);
        }

        String suffix = fileName.substring(fileName.lastIndexOf("."));
        Map<String, String> headerMapping = excelImportHeader.getHeaderMapping();
        String[][] insData = EasyExcel.readExcelDataToArray(inputStream, suffix, 0, 0);
        int row = insData.length;
        if (row < 2) {
            throw new BusinessException("999999", "无导入数据");
        }

        this.buildJoinInsValues(excelImportHeader);
        excelValueList = new ArrayList<>();
        for (int i = 1; i < row; i++) {
            int col = insData[i].length;
            JSONObject values = new JSONObject();
            for (int j = 0; j < col; j++) {
                String key = headerMapping.get(insData[0][j]);
                if (StringUtils.isNotBlank(key)) {
                    String value = insData[i][j];
                    values.put(key, value.trim());
                }
            }
            if (values.size() > 0) {
                excelValueList.add(values);
                values.put("index", i);
//                addInstanceData(excelImportHeader, values, i);
            }
        }

        if (CollectionUtil.isNotEmpty(excelValueList)) {
            if (excelValueList.size() > 10000) {
                throw new BusinessException("999999", String.format("导入数据最多1000条，本次导入%s条超出10000条，导入不支持，请拆分后再导入！", excelValueList.size()));
            }

            excelValueList.forEach(values -> {
                System.out.println(System.currentTimeMillis());
                Integer index = values.getInteger("index");
                values.remove("index");
                addInstanceData(excelImportHeader, values, index);
                System.out.println(System.currentTimeMillis());
            });
        }
        return true;
    }


    private void addInstanceData(ExcelImportHeader excelImportHeader, JSONObject values, int rowIndex) {
        String model = excelImportHeader.getModel();
        String className = excelImportHeader.getClassName();
        boolean isHier = excelImportHeader.isHierFlag();
        long containerId = excelImportHeader.getContainerId();
        String parentId = excelImportHeader.getParentId();
        String type = excelImportHeader.getType();
        List<ImportValidationRule> rules = excelImportHeader.getRules();
        String msg = validationRule(rules, values);
        if (StringUtils.isNotBlank(msg)) {
            throw new BusinessException("999999", String.format("数据导入%s行，%s", rowIndex, msg));
        }
        Map<String, Object> initValues = excelImportHeader.getInitValues();
        Map<String, Object> initHierValues = excelImportHeader.getInitHierValues();
        String tempParentId = values.getString("parentId");

        Map<String, Object> tempValues;
        if (StringUtils.isBlank(tempParentId) || "root".equalsIgnoreCase(tempParentId)) {
            tempValues = initValues;
        } else {
            tempValues = initHierValues;
        }
        if (tempValues != null && tempValues.size() > 0) {
            for (Map.Entry<String, Object> entry : tempValues.entrySet()) {
                String value = String.valueOf(entry.getValue());
                String oldValue = values.getString(entry.getKey());
                if (StringUtils.isNotBlank(value) && value.equalsIgnoreCase("autouuid")) {
                    values.put(entry.getKey(), UuidTool.getUUID32());
                } else if (StringUtils.isBlank(oldValue)) {
                    values.put(entry.getKey(), entry.getValue());
                }
            }
        }

        try {
            values = autoGenUtil.handleAutoGenValue(values);
            this.dealJoinInsValues(excelImportHeader, values);
            this.dealLocalOption(excelImportHeader, values);
            this.dealJsonFields(excelImportHeader, values, rowIndex);
            this.dealArrayFields(excelImportHeader, values, rowIndex);
            if (isHier) {
                String newParentId = values.getString("parentId");
                if (StringUtils.isBlank(newParentId)) {
                    newParentId = excelImportHeader.getParentId();
                }
                String nodeId = values.getString("nodeId");
                if (StringUtils.isBlank(nodeId)) {
                    nodeId = UuidTool.getUUID32();
                }

                Long newContainerId = values.getLong("containerId");
                if (newContainerId == null) {
                    newContainerId = excelImportHeader.getContainerId();
                }
                addHierInstance(model, className, newContainerId, newParentId, nodeId, values);
            } else {
                addInstance(model, type, className, values);
            }
        } catch (Exception ex) {
            throw new BusinessException("999999", String.format("第%s行导入数据异常%s，保存失败！", rowIndex + 1, ex));
        }
    }

    private void dealJsonFields(ExcelImportHeader excelImportHeader, JSONObject values, int rowIndex) {
        List<String> jsonFields = excelImportHeader.getJsonFields();
        if (CollectionUtil.isNotEmpty(jsonFields)) {
            jsonFields.forEach(f -> {
                String jsonStr = values.getString(f);
                try {
                    if (StringUtils.isNotBlank(jsonStr)) {
                        values.put(f, JSON.parseObject(jsonStr));
                    }
                } catch (Exception ex) {
                    throw new BusinessException("999999", String.format("第%s行将%s转成JSONObject异常%s，保存失败！", rowIndex, f, ex));
                }
            });
        }
    }


    private void dealArrayFields(ExcelImportHeader excelImportHeader, JSONObject values, int rowIndex) {
        List<String> arrayFields = excelImportHeader.getArrayFields();
        if (CollectionUtil.isNotEmpty(arrayFields)) {
            arrayFields.forEach(f -> {
                String jsonArrayStr = values.getString(f);
                try {
                    if (StringUtils.isNotBlank(jsonArrayStr)) {
                        values.put(f, JSON.parseArray(jsonArrayStr));
                    }
                } catch (Exception ex) {
                    throw new BusinessException("999999", String.format("第%s行将%s转成JSONArray异常%s，保存失败！", rowIndex, f, ex));
                }
            });
        }
    }

    /**
     * 处理本地选项
     *
     * @param excelImportHeader
     * @param values
     */
    private void dealLocalOption(ExcelImportHeader excelImportHeader, JSONObject values) {
        JSONObject localOption = excelImportHeader.getLocalOption();
        if (localOption == null) {
            return;
        }
        for (String key : localOption.keySet()) {
            // 获取键对应的值
            JSONObject optionObj = localOption.getJSONObject(key);
            if (optionObj == null) {
                continue;
            }
            String imPortValue = values.getString(key);
            if (StringUtils.isNotBlank(imPortValue)) {
                values.put(key, optionObj.getString(imPortValue));
            }
        }
    }

    private void dealJoinInsValues(ExcelImportHeader excelImportHeader, JSONObject values) {
        List<ImportJoinInfo> joinList = excelImportHeader.getJoin();
        if (CollectionUtil.isEmpty(joinList)) {
            return;
        }
        for (ImportJoinInfo info : joinList) {
            String fieldName = info.getFieldName();
            String joinFieldName = info.getJoinFieldName();
            List<JSONObject> valueList = info.getValueList();
            if (CollectionUtil.isEmpty(valueList)) {
                continue;
            }
            String fieldNameValue = values.getString(fieldName);
            if (StringUtils.isBlank(fieldNameValue)) {
                continue;
            }
            Map<String, String> joinFieldMap = new HashMap<>();
            List<String> joinFieldList = info.getJoinFieldMap();
            joinFieldList.forEach(j -> {
                String[] split = j.trim().split("\\:");
                if (split.length == 2) {
                    joinFieldMap.put(split[0], split[1]);
                }
            });
            JSONObject jsonObject = valueList.stream().filter(v -> fieldNameValue.equalsIgnoreCase(v.getString(joinFieldName))).findFirst().orElse(null);
            if (jsonObject == null) {
                reBuildJoinInsValues(info);
                valueList = info.getValueList();
                jsonObject = valueList.stream().filter(v -> fieldNameValue.equalsIgnoreCase(v.getString(joinFieldName))).findFirst().orElse(null);
                if (jsonObject == null) {
                    jsonObject = excelValueList.stream().filter(v -> fieldNameValue.equalsIgnoreCase(v.getString(joinFieldName))).findFirst().orElse(null);
                }
            }

            JSONObject finalJsonObject = jsonObject;
            if (finalJsonObject == null) {
                continue;
            }
            joinFieldMap.forEach((key, value) -> {
                values.put(key, finalJsonObject.get(value));
            });
        }
    }


    private void buildJoinInsValues(ExcelImportHeader excelImportHeader) {
        List<ImportJoinInfo> join = excelImportHeader.getJoin();
        if (CollectionUtil.isEmpty(join)) {
            return;
        }
        List<ImportJoinInfo> joinList = excelImportHeader.getJoin();
        joinList.forEach(info -> {
            reBuildJoinInsValues(info);
        });
    }

    private void reBuildJoinInsValues(ImportJoinInfo info) {
        String model = info.getModel();
        String className = info.getClassName();
        List<JSONObject> jsonObjectList;
        switch (model) {
            case "logic":
                jsonObjectList = this.logicInstanceDslService.queryWithoutHier(null, className, null);
                setImportJoinInfo(jsonObjectList, info);
                break;
            case "consume":
                jsonObjectList = this.consumeInstanceDslService.query(null, className, null);
                setImportJoinInfo(jsonObjectList, info);
                break;
            case "resource":
                jsonObjectList = this.resourceInstanceDslService.query(null, className, null);
                setImportJoinInfo(jsonObjectList, info);
                break;
            case "tank":
                jsonObjectList = this.tankInstanceDslService.queryWithoutHier(null, className, null);
                setImportJoinInfo(jsonObjectList, info);
                break;
            case "staticLogic":
            case "twins":
                List<HierInstance> hierInsList = this.hierInstanceDslService.query(model, className, null);
                if (CollectionUtil.isNotEmpty(hierInsList)) {
                    List<JSONObject> valueList = hierInsList.stream().map(hierIns -> {
                        JSONObject jsonValues = hierIns.getValues();
                        jsonValues.put("id", hierIns.getId());
                        jsonValues.put("nodeId", hierIns.getNodeId());
                        jsonValues.put("parentId", hierIns.getParentId());
                        return jsonValues;
                    }).collect(Collectors.toList());
                    info.setValueList(valueList);
                }
                break;
            default:
                break;
        }
    }

    private void setImportJoinInfo(List<JSONObject> jsonObjectList, ImportJoinInfo info) {
        if (CollectionUtil.isNotEmpty(jsonObjectList)) {
            List<JSONObject> valueList = jsonObjectList.stream().map(jsonObject -> {
                JSONObject jsonValues = jsonObject.getJSONObject("values");
                jsonValues.put("id", jsonObject.getLong("id"));
                return jsonValues;
            }).collect(Collectors.toList());
            info.setValueList(valueList);
        }
    }

    private void addInstance(String model, String type, String className, JSONObject values) {
        switch (model) {
            case "logic":
                this.logicInstanceDslService.add(type, className, UuidTool.getUUID32(), values);
                break;
            case "consume":
                this.consumeInstanceDslService.add(type, className, UuidTool.getUUID32(), values);
                break;
            case "resource":
                this.resourceInstanceDslService.add(type, className, UuidTool.getUUID32(), values);
                break;
            case "tank":
                this.tankInstanceDslService.add(type, className, UuidTool.getUUID32(), values);
                break;
            default:
                break;
        }
    }

    private String validationRule(List<ImportValidationRule> rules, JSONObject values) {
        if (CollectionUtil.isEmpty(rules)) {
            return "";
        }

        for (ImportValidationRule rule : rules) {
            String model = rule.getModel();
            String className = rule.getClassName();
            String fieldType = rule.getFieldType().toLowerCase();
            String excelFieldName = rule.getFieldName();
            String modelFieldName = rule.getModelFieldName();
            String fieldValue = values.getString(excelFieldName);
            String condition = transCondition(modelFieldName, fieldType, fieldValue);
            boolean hasRecord = rule.isHasRecord();
            boolean hier = rule.isHierFlag();
            boolean valid;
            if (hier) {
                valid = validationHierInstance(model, className, condition);
            } else {
                valid = validationInstance(model, className, condition);
            }
            if (hasRecord != valid) {
                return String.format("属性值：%s数据%s,导入失败！", fieldValue, hasRecord ? "不存在" : "已存在");
            }
        }
        return "";
    }

    private boolean validationInstance(String model, String className, String condition) {
        List<JSONObject> jsonObjectList = new ArrayList<>();
        switch (model) {
            case "logic":
                jsonObjectList = this.logicInstanceDslService.query(condition, className, null);
                break;
            case "consume":
                jsonObjectList = this.consumeInstanceDslService.query(condition, className, null);
                break;
            case "resource":
                jsonObjectList = this.resourceInstanceDslService.query(condition, className, null);
                break;
            case "tank":
                jsonObjectList = this.tankInstanceDslService.query(condition, className, null);
                break;
            default:
                break;
        }

        if (CollectionUtil.isNotEmpty(jsonObjectList)) {
            return true;
        } else {
            return false;
        }
    }

    private boolean validationHierInstance(String model, String className, String condition) {
        List<HierInstance> hierInstances = hierInstanceDslService.query(model, className, condition);
        if (CollectionUtil.isNotEmpty(hierInstances)) {
            return true;
        } else {
            return false;
        }
    }

    private String transCondition(String fieldName, String fieldType, String oValue) {
        String condition = "";
        switch (fieldType) {
            case "date":
            case "datetime":
            case "string":
                condition = fieldName + " = '" + oValue + "'";
                break;
            case "boolean":
                boolean dataValue = Boolean.valueOf(oValue);
                if (dataValue) {
                    condition = fieldName + " = 1 ";
                } else {
                    condition = fieldName + " = 0 ";
                }
                break;
            default:
                condition = fieldName + " = " + oValue;
                break;
        }

        return condition;
    }

    private void addHierInstance(String model, String className, long containerId, String parentId, String nodeId, JSONObject values) {
        JSONObject childJson = new JSONObject();
        values.remove("parentId");
        values.remove("nodeId");
        childJson.put("values", values);
        childJson.put("containerId", containerId);
        childJson.put("containerModel", model);
        childJson.put("className", className);
        childJson.put("parentId", parentId);
        childJson.put("nodeId", nodeId);
        hierInstanceDslService.addChild(childJson);
    }

    /**
     * 数采设备报警设置
     *
     * @param values 报警信息
     * @return 返回成功失败
     */
    public ResultInfo<?> addEquipAlarm(JSONObject values) {
        try {
            this.logicInstanceDslService.add("logic", "messageAlarm", UuidTool.getUUID32(), values);
            return JsonResult.success(StatusCode.SUCCESS);
        } catch (Exception ex) {
            throw new BusinessException("999999", "添加设备报警信息异常" + ex);
        }
    }
}
